#include <linux/module.h>
#include <linux/kthread.h>
#include <linux/delay.h>

MODULE_LICENSE("GPL");
MODULE_AUTHOR("MAGC");
MODULE_DESCRIPTION("Magc Module Compile");

#define MAX_KTHREAD     10
static struct task_struct *threads[MAX_KTHREAD];
//静态初始化一个锁
//static DEFINE_SPINLOCK(threads_lock);
static spinlock_t thread_spinlock;

//定义被保护的数据

struct our_data{
    int count1;
    int count2;
};

static struct our_data my_data;
static void show_data(void)
{
    printk("my_data.count1 = %d ; my_data.count2 = %d\n",my_data.count1 , my_data.count2);
}

/**
 * @brief 在线程运行过程中，让它等待，直到让它stop为止
 *
 * @param data
 *
 * @return 
 */
static int thread_do(void *data)
{
    printk("run ....");
    while(!kthread_should_stop())
    {
        spin_lock(&thread_spinlock);
        my_data.count1 ++ ;
        my_data.count2 += 10;
        spin_unlock(&thread_spinlock);
        msleep(10);
    }
    return 0;
}

static int create_thread(void)
{
    int i;
    for (i = 0; i < MAX_KTHREAD; ++i) {
        struct task_struct *thread;
        thread = kthread_run(thread_do ,NULL,"thread-%d",i);
        if (IS_ERR(thread))
            return -1;
        threads[i] = thread;
    }
    return 0;
}

/**
 * @brief 在此处按顺序去停止线程时，有些线程有可能已经结束退出了，会产生非法指针访问的情况
 * 所以，在线程运行过程中让它等待一段时间，直到让它stop为止
 */
static void cleanup_threads(void)
{
    int i;
    for (i = 0; i < MAX_KTHREAD; ++i) {
        if(threads[i])
            kthread_stop(threads[i]);
        
    }
}
static int minit(void)
{
    printk("call %s \n",__FUNCTION__);
    if(create_thread())
        goto err;
    return 0;
err:
    cleanup_threads();
    return -1;
}

static void mexit(void)
{

    printk("call %s \n",__FUNCTION__);
    show_data();
    cleanup_threads();
}
module_init(minit);
module_exit(mexit);
